home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / WindowMaker / src / application.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-03-10  |  13.0 KB  |  526 lines

  1. /*
  2.  *  Window Maker window manager
  3.  * 
  4.  *  Copyright (c) 1997, 1998 Alfredo K. Kojima
  5.  *  Copyright (c) 1998       Dan Pascu
  6.  * 
  7.  *  This program is free software; you can redistribute it and/or modify
  8.  *  it under the terms of the GNU General Public License as published by
  9.  *  the Free Software Foundation; either version 2 of the License, or
  10.  *  (at your option) any later version.
  11.  *
  12.  *  This program is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *  GNU General Public License for more details.
  16.  *
  17.  *  You should have received a copy of the GNU General Public License
  18.  *  along with this program; if not, write to the Free Software
  19.  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 
  20.  *  USA.
  21.  */
  22. #include "wconfig.h"
  23.  
  24. #include <X11/Xlib.h>
  25.  
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <unistd.h>
  29.  
  30. #include "WindowMaker.h"
  31. #include "menu.h"
  32. #include "window.h"
  33. #ifdef USER_MENU
  34. #include "usermenu.h"
  35. #endif /* USER_MENU */
  36. #include "icon.h"
  37. #include "appicon.h"
  38. #include "application.h"
  39. #include "appmenu.h"
  40. #include "properties.h"
  41. #include "funcs.h"
  42. #include "stacking.h"
  43. #include "actions.h"
  44. #include "defaults.h"
  45. #include "workspace.h"
  46.  
  47. #include "dock.h"
  48.  
  49. #ifdef WMSOUND
  50. #include "wmsound.h"
  51. #endif
  52.  
  53.  
  54. /******** Global variables ********/
  55.  
  56. extern XContext wAppWinContext;
  57. extern XContext wWinContext;
  58. extern WPreferences wPreferences;
  59.  
  60. extern WDDomain *WDWindowAttributes;
  61.  
  62. /******** Local variables ********/
  63.  
  64.  
  65. static WWindow*
  66. makeMainWindow(WScreen *scr, Window window)
  67. {
  68.     WWindow *wwin;
  69.     XWindowAttributes attr;
  70.  
  71.     if (!XGetWindowAttributes(dpy, window, &attr)) {
  72.     return NULL;
  73.     }
  74.  
  75.     wwin = wWindowCreate();
  76.     wwin->screen_ptr = scr;
  77.     wwin->client_win = window;
  78.     wwin->main_window = window;
  79.     wwin->wm_hints = XGetWMHints(dpy, window);
  80. /*    if (!MyXFetchName(dpy, window, &(wwin->frame->title))) {
  81.     wwin->frame->title = NULL;
  82.     }
  83.  */
  84.     PropGetWMClass(window, &wwin->wm_class, &wwin->wm_instance);
  85.  
  86.  
  87.     wDefaultFillAttributes(scr, wwin->wm_instance, wwin->wm_class,
  88.                &wwin->user_flags, &wwin->defined_user_flags, True);
  89.     
  90.     XSelectInput(dpy, window, attr.your_event_mask | PropertyChangeMask
  91.          | StructureNotifyMask );
  92.     return wwin;
  93. }
  94.  
  95.  
  96. WApplication*
  97. wApplicationOf(Window window)
  98. {
  99.     WApplication *wapp;
  100.  
  101.     if (window == None) 
  102.       return NULL;
  103.     if (XFindContext(dpy, window, wAppWinContext, (XPointer*)&wapp)!=XCSUCCESS)
  104.       return NULL;
  105.     return wapp;
  106. }
  107.  
  108.  
  109. static WAppIcon*
  110. findDockIconFor(WDock *dock, Window main_window)
  111. {
  112.     WAppIcon *aicon = NULL;
  113.  
  114.     aicon = wDockFindIconForWindow(dock, main_window);
  115.     if (!aicon) {
  116.         wDockTrackWindowLaunch(dock, main_window);
  117.         aicon = wDockFindIconForWindow(dock, main_window);
  118.     }
  119.     return aicon;
  120. }
  121.  
  122.  
  123. static void
  124. extractIcon(WWindow *wwin)
  125. {
  126.     int argc;
  127.     char **argv;
  128.     
  129.     if (!XGetCommand(dpy, wwin->client_win, &argv, &argc) || argc < 1)
  130.     return;
  131.  
  132.     wApplicationExtractDirPackIcon(wwin->screen_ptr,argv[0], 
  133.                    wwin->wm_instance,
  134.                    wwin->wm_class);
  135.     XFreeStringList(argv);
  136. }
  137.  
  138.  
  139. static void
  140. saveIconNameFor(char *iconPath, char *wm_instance, char *wm_class)
  141. {
  142.     proplist_t dict = WDWindowAttributes->dictionary;
  143.     proplist_t adict, key, iconk;
  144.     proplist_t val;
  145.     char *tmp;
  146.     int i;
  147.     
  148.     i = 0;
  149.     if (wm_instance)
  150.     i += strlen(wm_instance);
  151.     if (wm_class)
  152.     i += strlen(wm_class);
  153.  
  154.     tmp = wmalloc(i+8);
  155.     *tmp = 0;
  156.     if (wm_class && wm_instance) {
  157.     sprintf(tmp, "%s.%s", wm_instance, wm_class);
  158.     } else {
  159.     if (wm_instance)
  160.         strcat(tmp, wm_instance);
  161.     if (wm_class)
  162.         strcat(tmp, wm_class);
  163.     }
  164.     
  165.     key = PLMakeString(tmp); 
  166.     free(tmp);
  167.     adict = PLGetDictionaryEntry(dict, key);
  168.     
  169.     iconk = PLMakeString("Icon");
  170.     
  171.     if (adict) {
  172.     val = PLGetDictionaryEntry(adict, iconk);
  173.     } else {
  174.     /* no dictionary for app, so create one */
  175.     adict = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
  176.     PLInsertDictionaryEntry(dict, key, adict);
  177.     PLRelease(adict);
  178.     val = NULL;
  179.     }
  180.     if (!val) {
  181.     val = PLMakeString(iconPath);
  182.     PLInsertDictionaryEntry(adict, iconk, val);
  183.     PLRelease(val);
  184.     }
  185.     PLRelease(key);
  186.  
  187.     if (val && !wPreferences.flags.noupdates)
  188.     PLSave(dict, YES);
  189. }
  190.  
  191.  
  192. void
  193. wApplicationExtractDirPackIcon(WScreen *scr, char *path, 
  194.                 char *wm_instance, char *wm_class)
  195. {
  196.     char *iconPath=NULL;
  197.     /* Maybe the app is a .app and it has an icon in it, like
  198.      * /usr/local/GNUstep/Apps/WPrefs.app/WPrefs.tiff
  199.      */
  200.     if (strstr(path, ".app")) {
  201.     char *tmp;
  202.     
  203.     tmp = wmalloc(strlen(path)+16);
  204.     
  205.     if (scr->flags.supports_tiff) {
  206.         strcpy(tmp, path);
  207.         strcat(tmp, ".tiff");
  208.         if (access(tmp, R_OK)==0)
  209.         iconPath = tmp;
  210.     }
  211.     if (!path) {
  212.         strcpy(tmp, path);
  213.         strcat(tmp, ".xpm");
  214.         if (access(tmp, R_OK)==0)
  215.         iconPath = tmp;
  216.     }
  217.     if (!iconPath)
  218.         free(tmp);
  219.     }
  220.     
  221.     if (iconPath) {
  222.     saveIconNameFor(iconPath, wm_instance, wm_class);
  223.  
  224.     free(iconPath);
  225.     }
  226. }
  227.  
  228.  
  229. static Bool
  230. extractClientIcon(WAppIcon *icon)
  231. {
  232.     char *path;
  233.  
  234.     path = wIconStore(icon->icon);
  235.     if (!path)
  236.     return False;
  237.  
  238.     saveIconNameFor(path, icon->wm_instance, icon->wm_class);
  239.  
  240.     free(path);
  241.  
  242.     return True;
  243. }
  244.  
  245.  
  246. WApplication*
  247. wApplicationCreate(WScreen *scr, Window main_window)
  248. {
  249.     WApplication *wapp;
  250.     WWindow *leader;
  251.  
  252.     if (main_window==None || main_window==scr->root_win) {
  253. #ifdef DEBUG0
  254.     wwarning("trying to create application for %x",(unsigned)main_window);
  255. #endif
  256.     return NULL;
  257.     }
  258.  
  259.     {
  260.     Window root;
  261.     int foo;
  262.     unsigned int bar;
  263.     /* check if the window is valid */
  264.     if (!XGetGeometry(dpy, main_window, &root, &foo, &foo, &bar, &bar,
  265.               &bar, &bar)) {
  266.         return NULL;
  267.     }
  268.     }
  269.     
  270.     wapp = wApplicationOf(main_window);
  271.     if (wapp) {
  272.     wapp->refcount++;
  273.     return wapp;
  274.     }
  275.     
  276.     wapp = wmalloc(sizeof(WApplication));
  277.     memset(wapp, 0, sizeof(WApplication));
  278.  
  279.     wapp->refcount = 1;
  280.     wapp->last_focused = NULL;
  281.     
  282.     wapp->last_workspace = 0;
  283.       
  284.     wapp->main_window = main_window;
  285.     wapp->main_window_desc = makeMainWindow(scr, main_window);
  286.     if (!wapp->main_window_desc) {
  287.     free(wapp);
  288.     return NULL;
  289.     }
  290.     
  291.     extractIcon(wapp->main_window_desc);
  292.  
  293.     leader = wWindowFor(main_window);
  294.     if (leader) {
  295.     leader->main_window = main_window;
  296.     }
  297.     wapp->menu = wAppMenuGet(scr, main_window);
  298. #ifdef USER_MENU
  299.     if (!wapp->menu) wapp->menu = wUserMenuGet(scr, wapp->main_window_desc);
  300. #endif /* USER_MENU */
  301.  
  302.  
  303.     /*
  304.      * Set application wide attributes from the leader.
  305.      */
  306.     wapp->flags.hidden = WFLAGP(wapp->main_window_desc, start_hidden);
  307.     
  308.     wapp->flags.emulated = WFLAGP(wapp->main_window_desc, emulate_appicon);
  309.  
  310.     /* application descriptor */
  311.     XSaveContext(dpy, main_window, wAppWinContext, (XPointer)wapp);
  312.  
  313.     if (!WFLAGP(wapp->main_window_desc, no_appicon)) {
  314.         wapp->app_icon = NULL;
  315.         if (scr->last_dock)
  316.             wapp->app_icon = findDockIconFor(scr->last_dock, main_window);
  317.         /* check main dock if we did not find it in last dock */
  318.         if (!wapp->app_icon && scr->dock) {
  319.         wapp->app_icon = findDockIconFor(scr->dock, main_window);
  320.     }
  321.         /* finally check clips */
  322.         if (!wapp->app_icon) {
  323.             int i;
  324.             for (i=0; i<scr->workspace_count; i++) {
  325.                 WDock *dock = scr->workspaces[i]->clip;
  326.                 if (dock)
  327.                     wapp->app_icon = findDockIconFor(dock, main_window);
  328.                 if (wapp->app_icon)
  329.                     break;
  330.             }
  331.         }
  332.                     
  333.         if (wapp->app_icon) {
  334.             WWindow *mainw = wapp->main_window_desc;
  335.  
  336.             wapp->app_icon->running = 1;
  337.             wapp->app_icon->icon->force_paint = 1;
  338.             wapp->app_icon->icon->owner = mainw;
  339.             if (mainw->wm_hints && (mainw->wm_hints->flags&IconWindowHint))
  340.                 wapp->app_icon->icon->icon_win = mainw->wm_hints->icon_window;
  341.             wAppIconPaint(wapp->app_icon);
  342.         } else {
  343.         wapp->app_icon = wAppIconCreate(wapp->main_window_desc);
  344. #ifdef REDUCE_APPICONS
  345.     /* This is so we get the appearance of invoking the app sitting
  346.      * on the dock. -cls */
  347.         if (wapp->app_icon) {
  348.         if (wapp->app_icon->docked && wapp->app_icon->num_apps == 1) {
  349.             wapp->app_icon->launching = 0;
  350.             wapp->app_icon->running = 1;
  351.             wapp->app_icon->icon->force_paint = 1;
  352.             wAppIconPaint(wapp->app_icon);
  353.         }
  354.         }
  355. #endif
  356.     }
  357.     } else {
  358.     wapp->app_icon = NULL;
  359.     }
  360.     
  361.     if (wapp->app_icon) {
  362.         wapp->app_icon->main_window = main_window;
  363.     }
  364.  
  365. #ifndef REDUCE_APPICONS
  366.     if (wapp->app_icon && !wapp->app_icon->docked) {
  367. #else
  368.     if (wapp->app_icon && !wapp->app_icon->docked && wapp->app_icon->num_apps == 1) {
  369. #ifdef THIS_SUCKS
  370.     }
  371. #endif
  372. #endif
  373.         WIcon *icon = wapp->app_icon->icon;
  374.         WDock *clip = scr->workspaces[scr->current_workspace]->clip;
  375.         int x=0, y=0;
  376.  
  377.         if (clip && clip->attract_icons && wDockFindFreeSlot(clip, &x, &y)) {
  378.             wapp->app_icon->attracted = 1;
  379.             if (!wapp->app_icon->icon->shadowed) {
  380.                 wapp->app_icon->icon->shadowed = 1;
  381.                 wapp->app_icon->icon->force_paint = 1;
  382.                 /* We don't do an wAppIconPaint() here because it's in
  383.                  * wDockAttachIcon(). -Dan.
  384.                  */
  385.             }
  386.             wDockAttachIcon(clip, wapp->app_icon, x, y);
  387.         } else {
  388.             PlaceIcon(scr, &x, &y);
  389.         wAppIconMove(wapp->app_icon, x, y);
  390.         wLowerFrame(icon->core);
  391.         }
  392.         if (!clip || !wapp->app_icon->attracted || !clip->collapsed)
  393.         XMapWindow(dpy, icon->core->window);
  394.     }
  395.  
  396.     if (wPreferences.auto_arrange_icons && wapp->app_icon && !wapp->app_icon->attracted) {
  397.     wArrangeIcons(scr, True);
  398.     }
  399.  
  400.     if (wapp->app_icon) {
  401.     char *tmp;
  402.  
  403.     /* if the displayed icon was supplied by the client, save the icon */
  404.     tmp = wDefaultGetIconFile(scr, wapp->app_icon->wm_instance,
  405.                   wapp->app_icon->wm_class, True);
  406.     if (!tmp)
  407.         extractClientIcon(wapp->app_icon);
  408.     }
  409.     
  410.     wapp->prev = NULL; 
  411.     wapp->next = scr->wapp_list;
  412.     if (scr->wapp_list)
  413.     scr->wapp_list->prev = wapp;
  414.     scr->wapp_list = wapp;
  415.  
  416.     
  417. #ifdef WMSOUND
  418.     wSoundPlay(WMSOUND_APPSTART);
  419. #endif
  420.  
  421. #ifdef DEBUG
  422.     printf("Created application for %x\n", (unsigned)main_window);
  423. #endif
  424.     return wapp;
  425. }
  426.  
  427.  
  428. void
  429. wApplicationDestroy(WApplication *wapp)
  430. {
  431.     Window main_window;
  432.     WWindow *wwin;
  433.     WScreen *scr;
  434. #ifdef REDUCE_APPICONS
  435.     unsigned int napps;
  436. #endif
  437.  
  438.     if (!wapp)
  439.       return;
  440.   
  441.     wapp->refcount--;
  442.     if (wapp->refcount>0)
  443.       return;
  444.  
  445.  
  446.     scr = wapp->main_window_desc->screen_ptr;
  447.     main_window = wapp->main_window;
  448. #ifdef REDUCE_APPICONS
  449.     napps = wAppIconReduceAppCount(wapp);
  450. #endif
  451.  
  452.     if (wapp == scr->wapp_list) {
  453.         if (wapp->next)
  454.             wapp->next->prev = NULL;
  455.         scr->wapp_list = wapp->next;
  456.     } else {
  457.         if (wapp->next)
  458.             wapp->next->prev = wapp->prev;
  459.         if (wapp->prev)
  460.             wapp->prev->next = wapp->next;
  461.     }
  462.  
  463.     XDeleteContext(dpy, wapp->main_window, wAppWinContext);
  464.     wAppMenuDestroy(wapp->menu);
  465.     if (wapp->app_icon) {
  466.         if (wapp->app_icon->docked && !wapp->app_icon->attracted) {
  467. #ifdef REDUCE_APPICONS
  468.         if (napps == 0) {
  469. #endif
  470.         wapp->app_icon->running = 0;
  471.         /* since we keep it, we don't care if it was attracted or not */
  472.         wapp->app_icon->attracted = 0;
  473.         wapp->app_icon->icon->shadowed = 0;
  474.         wapp->app_icon->main_window = None;
  475.         wapp->app_icon->pid = 0;
  476.         wapp->app_icon->icon->owner = NULL;
  477.         wapp->app_icon->icon->icon_win = None;
  478.         wapp->app_icon->icon->force_paint = 1;
  479.         wAppIconPaint(wapp->app_icon);
  480. #ifdef REDUCE_APPICONS
  481.         }
  482. #endif
  483.         } else if (wapp->app_icon->docked) {
  484. #ifdef REDUCE_APPICONS
  485.         if (napps == 0)  {
  486. #endif
  487.         wapp->app_icon->running = 0;
  488.         wDockDetach(wapp->app_icon->dock, wapp->app_icon);
  489. #ifdef REDUCE_APPICONS
  490.         }
  491. #endif 
  492.         } else {
  493. #ifdef REDUCE_APPICONS
  494.             if (napps == 0) {
  495. #endif 
  496.         wAppIconDestroy(wapp->app_icon);
  497. #ifdef REDUCE_APPICONS
  498.             }
  499. #endif
  500.     }
  501.     }
  502.     wwin = wWindowFor(wapp->main_window_desc->client_win);
  503.  
  504.     wWindowDestroy(wapp->main_window_desc);
  505.     if (wwin) {
  506.         /* undelete client window context that was deleted in
  507.           * wWindowDestroy */
  508.         XSaveContext(dpy, wwin->client_win, wWinContext, 
  509.              (XPointer)&wwin->client_descriptor);
  510.     }
  511.     free(wapp);
  512.     
  513. #ifdef DEBUG
  514.     printf("Destroyed application for %x\n", (unsigned)main_window);
  515. #endif
  516.     if (wPreferences.auto_arrange_icons) {
  517.         wArrangeIcons(scr, True);
  518.     }
  519.  
  520. #ifdef WMSOUND
  521.     wSoundPlay(WMSOUND_APPEXIT);
  522. #endif
  523. }
  524.  
  525.  
  526.